Passed
Pull Request — develop (#758)
by Kevin Van
10:13 queued 04:10
created

PlayerDetail   A

Complexity

Total Complexity 24

Size/Duplication

Total Lines 385
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 24
eloc 332
dl 0
loc 385
rs 10
c 0
b 0
f 0

14 Functions

Rating   Name   Duplication   Size   Complexity  
A renderPlayerPosition 0 11 1
A render 0 20 1
A renderPlayerBirthdate 0 5 1
A renderPlayerBody 0 10 1
B renderPlayerGamesFull 0 96 3
B renderPlayerStats 0 42 7
A renderPlayerName 0 5 1
A updateData 0 12 2
B renderPlayerStatsFull 0 87 2
A renderPlayerData 0 6 1
A renderPlayerHeader 0 9 1
A renderPlayerJoinDate 0 17 1
A componentDidMount 0 3 1
A renderPlayerImage 0 14 1
1
import { StaticQuery, graphql } from "gatsby"
2
import { Link } from "gatsby"
3
import { getSrc } from "gatsby-plugin-image"
4
import moment from "moment"
5
import React, { Component, Fragment } from "react"
6
import Helmet from "react-helmet"
7
import { StringParam, useQueryParam } from "use-query-params"
8
9
import Icon from "../components/Icon"
10
import RelatedNews from "../components/RelatedNews"
11
import iconCardRed from "../images/i_card_red.png"
12
import iconCardYellow from "../images/i_card_yellow.png"
13
import iconCleansheet from "../images/i_cleansheet.png"
14
import iconGoal from "../images/i_goal.png"
15
import { mapPositionCode } from "../scripts/helper"
16
import Card from "./Card"
17
import "./player.scss"
18
19
// eslint-disable-next-line
20
String.prototype.replaceAll = function (search, replacement) {
21
  // eslint-disable-next-line @typescript-eslint/no-this-alias
22
  var target = this
23
  return target.replace(new RegExp(search, `g`), replacement)
24
}
25
26
/**
27
 */
28
class PlayerDetail extends Component {
29
  constructor(props) {
30
    super(props)
31
32
    this.state = {
33
      data: [],
34
      loading: true,
35
    }
36
37
    const {
38
      config: {
39
        site: {
40
          siteMetadata: { kcvvPsdApi },
41
        },
42
      },
43
      player: { field_vv_id: playerId },
44
    } = this.props
45
46
    this.kcvvPsdApi = kcvvPsdApi
47
    this.playerId = playerId
48
  }
49
50
  updateData() {
51
    if (this.playerId === null) {
52
      return
53
    }
54
55
    const apiUrl = `${this.kcvvPsdApi}/stats/player/${this.playerId}`
56
57
    fetch(apiUrl)
58
      .then((response) => response.json())
59
      .then((json) => this.setState({ data: json, loading: false }))
60
      .catch(() => this.setState({ data: {}, loading: false }))
61
  }
62
63
  componentDidMount() {
64
    this.updateData()
65
  }
66
67
  renderPlayerName = (player) => (
68
    <h1 className={`player-detail__name`}>
69
      <span className={`player-detail__name-first`}>{player.field_firstname}</span>
70
      <span className={`player-detail__name-last`}>{player.field_lastname}</span>
71
    </h1>
72
  )
73
  renderPlayerImage = (player) => (
74
    <div className={`bg-green-mask`}>
75
      <div
76
        className={`player-detail__bg-avatar`}
77
        style={
78
          player.relationships.field_image && {
79
            backgroundImage: `url(${getSrc(
80
              player.relationships.field_image.localFile.childImageSharp.gatsbyImageData
81
            )})`,
82
          }
83
        }
84
      />
85
      <div className={`bg-white-end`} />
86
    </div>
87
  )
88
  renderPlayerHeader = (player) => (
89
    <header className={`player-detail__header`}>
90
      {this.renderPlayerName(player)}
91
      {this.renderPlayerImage(player)}
92
93
      <div className={`player-detail__bg-shirt-number`} aria-hidden="true">
94
        {player.field_shirtnumber || ``}
95
      </div>
96
    </header>
97
  )
98
  renderPlayerStats = (player) => {
99
    if (this.state.loading === false && this.state.data) {
100
      const { playerStatistics = [] } = this.state.data
101
102
      return (
103
        <aside className={`player-detail__statistics`}>
104
          <section className={`player-detail__statistics-item`}>
105
            <div className={`player-detail__statistics-item__number`}>
106
              {playerStatistics.reduce((a, b) => a + (b?.gamesPlayed || 0), 0) || `0`}
107
            </div>
108
            <div className={`player-detail__statistics-item__label`}>Wedstrijden</div>
109
          </section>
110
111
          {(player.field_position === `k` || player.field_position === `d`) && (
112
            <section className={`player-detail__statistics-item`}>
113
              <div className={`player-detail__statistics-item__number`}>
114
                {playerStatistics.reduce((a, b) => a + (b?.cleanSheets || 0), 0) || `0`}
115
              </div>
116
              <div className={`player-detail__statistics-item__label`}>Cleansheets</div>
117
            </section>
118
          )}
119
          {player.field_position !== `k` && (
120
            <section className={`player-detail__statistics-item`}>
121
              <div className={`player-detail__statistics-item__number`}>
122
                {playerStatistics.reduce((a, b) => a + (b?.goals || 0), 0) || `0`}
123
              </div>
124
              <div className={`player-detail__statistics-item__label`}>Doelpunten</div>
125
            </section>
126
          )}
127
          <section className={`player-detail__statistics-item`}>
128
            <div className={`player-detail__statistics-item__number`}>
129
              {playerStatistics.reduce((a, b) => a + (b?.yellowCards || 0), 0) || `0`}
130
            </div>
131
            <div className={`player-detail__statistics-item__label`}>Gele kaarten</div>
132
          </section>
133
          <section className={`player-detail__statistics-item`}>
134
            <div className={`player-detail__statistics-item__number`}>
135
              {playerStatistics.reduce((a, b) => a + (b?.redCards || 0), 0) || `0`}
136
            </div>
137
            <div className={`player-detail__statistics-item__label`}>Rode kaarten</div>
138
          </section>
139
        </aside>
140
      )
141
    }
142
  }
143
144
  renderPlayerStatsFull = (player) => {
145
    if (this.state.loading === false && this.state.data) {
146
      const { playerStatistics = [] } = this.state.data
147
148
      return (
149
        <Card title="Statistieken" className={`player-detail__stats`} hasTable={true}>
150
          <table className={`player-detail__stats__table`}>
151
            <thead>
152
              <tr>
153
                <th className={`player-detail__column player-detail__column--string`}>Team</th>
154
                <th className={`player-detail__column player-detail__column--number show-for-medium`}>
155
                  <span title="Wedstrijden gespeeld">P</span>
156
                </th>
157
                <th className={`player-detail__column player-detail__column--number`}>
158
                  <span title="Wedstrijden gewonnen">W</span>
159
                </th>
160
                <th className={`player-detail__column player-detail__column--number`}>
161
                  <span title="Wedstrijden gelijkgespeeld">D</span>
162
                </th>
163
                <th className={`player-detail__column player-detail__column--number`}>
164
                  <span title="Wedstrijden verloren">L</span>
165
                </th>
166
                <th className={`player-detail__column player-detail__column--number`}>
167
                  <img
168
                    src={iconCardYellow}
169
                    title="Gele kaart"
170
                    alt="Gele kaart"
171
                    className="player-detail__stats--header_icon"
172
                  />
173
                </th>
174
                <th className={`player-detail__column player-detail__column--number`}>
175
                  <img
176
                    src={iconCardRed}
177
                    title="Rode kaart"
178
                    alt="Rode kaart"
179
                    className="player-detail__stats--header_icon"
180
                  />
181
                </th>
182
                <th className={`player-detail__column player-detail__column--number`}>
183
                  <img
184
                    src={iconGoal}
185
                    title="Doelpunt(en) gescoord"
186
                    alt="Doelpunt(en) gescoord"
187
                    className="player-detail__stats--header_icon"
188
                  />
189
                </th>
190
                <th className={`player-detail__column player-detail__column--number  show-for-medium`}>
191
                  <img
192
                    src={iconCleansheet}
193
                    title="Cleansheets"
194
                    alt="Cleansheets"
195
                    className="player-detail__stats--header_icon"
196
                  />
197
                </th>
198
                <th className={`player-detail__column player-detail__column--number`}>
199
                  <span title="Minuten gespeeld">
200
                    <Icon icon="fa-clock-o" />
201
                  </span>
202
                </th>
203
              </tr>
204
            </thead>
205
            <tbody>
206
              {playerStatistics.map(function (stats) {
207
                return (
208
                  <tr>
209
                    <td className={`player-detail__column player-detail__column--string`}>
210
                      {stats.team.replace(`Voetbal : `, ``)}
211
                    </td>
212
                    <td className={`player-detail__column player-detail__column--number show-for-medium`}>
213
                      {stats.gamesPlayed}
214
                    </td>
215
                    <td className={`player-detail__column player-detail__column--number`}>{stats.gamesWon}</td>
216
                    <td className={`player-detail__column player-detail__column--number`}>{stats.gamesEqual}</td>
217
                    <td className={`player-detail__column player-detail__column--number`}>{stats.gamesLost}</td>
218
                    <td className={`player-detail__column player-detail__column--number`}>{stats.yellowCards}</td>
219
                    <td className={`player-detail__column player-detail__column--number`}>{stats.redCards}</td>
220
                    <td className={`player-detail__column player-detail__column--number`}>{stats.goals}</td>
221
                    <td className={`player-detail__column player-detail__column--number show-for-medium`}>
222
                      {stats.cleanSheets}
223
                    </td>
224
                    <td className={`player-detail__column player-detail__column--number`}>{stats.minutes}'</td>
225
                  </tr>
226
                )
227
              })}
228
            </tbody>
229
          </table>
230
        </Card>
231
      )
232
    }
233
  }
234
  renderPlayerGamesFull = () => {
235
    if (this.state.loading === false && this.state.data) {
236
      const { gameReports = [] } = this.state.data
237
238
      return (
239
        <Card className={`player-detail__games`} title="Wedstrijden" hasTable={true}>
240
          <table className={`player-detail__games__table responsive-card-table`}>
241
            <thead>
242
              <tr>
243
                <th className={`player-detail__column player-detail__column--string`}>Team</th>
244
                <th className={`player-detail__column player-detail__column--string`}>Type</th>
245
                <th className={`player-detail__column player-detail__column--string`}>Datum</th>
246
                <th className={`player-detail__column player-detail__column--number`}>
247
                  <span title="Thuis/uit">H/A</span>
248
                </th>
249
                <th className={`player-detail__column player-detail__column--score`}>Score</th>
250
                <th className={`player-detail__column player-detail__column--string`}>Tegenstander</th>
251
                <th className={`player-detail__column player-detail__column--number`}>
252
                  <img
253
                    src={iconCardYellow}
254
                    title="Gele kaart"
255
                    alt="Gele kaart"
256
                    className="player-detail__stats--header_icon"
257
                  />
258
                </th>
259
                <th className={`player-detail__column player-detail__column--number`}>
260
                  <img
261
                    src={iconCardRed}
262
                    title="Rode kaart"
263
                    alt="Rode kaart"
264
                    className="player-detail__stats--header_icon"
265
                  />
266
                </th>
267
                <th className={`player-detail__column player-detail__column--number`}>
268
                  <img
269
                    src={iconGoal}
270
                    title="Doelpunten gescoord"
271
                    alt="Rode kaart"
272
                    className="player-detail__stats--header_icon"
273
                  />
274
                </th>
275
                <th className={`player-detail__column player-detail__column--number`}>
276
                  <span title="Minuten gespeeld">
277
                    <Icon icon="fa-clock-o" />
278
                  </span>
279
                </th>
280
              </tr>
281
            </thead>
282
            <tbody>
283
              {gameReports.map(function (game) {
284
                return (
285
                  <tr>
286
                    <td data-label="Team" className={`player-detail__column player-detail__column--string`}>
287
                      {game.team.replace(`Voetbal : `, ``)}
288
                    </td>
289
                    <td data-label="Type" className={`player-detail__column player-detail__column--string`}>
290
                      {game.competition}
291
                    </td>
292
                    <td data-label="Datum" className={`player-detail__column player-detail__column--string`}>
293
                      {moment(game.date).format(`DD/MM/YYYY`)}
294
                    </td>
295
                    <td data-label="Thuis/uit" className={`player-detail__column player-detail__column--number`}>
296
                      {game.home ? (
297
                        <span className={`player-detail__games__home`} title="Thuiswedstrijd">
298
                          <Icon icon="fa-home" alt="Thuiswedstrijd" />
299
                        </span>
300
                      ) : (
301
                        <span className={`player-detail__games__away`} title="Uitwedstrijd">
302
                          <Icon icon="fa-bus" alt="Uitwedstrijd" />
303
                        </span>
304
                      )}
305
                    </td>
306
                    <td data-label="Score" className={`player-detail__column player-detail__column--score`}>
307
                      {game.goalsHomeTeam}&nbsp;-&nbsp;{game.goalsAwayTeam}
308
                    </td>
309
                    <td data-label="Tegenstander" className={`player-detail__column player-detail__column--string`}>
310
                      {game.opponent}
311
                    </td>
312
                    <td data-label="Gele kaart(en)" className={`player-detail__column player-detail__column--number`}>
313
                      {game.yellowCards}
314
                    </td>
315
                    <td data-label="Rode kaart(en)" className={`player-detail__column player-detail__column--number`}>
316
                      {game.redCards}
317
                    </td>
318
                    <td data-label="Doelpunten" className={`player-detail__column player-detail__column--number`}>
319
                      {game.goals}
320
                    </td>
321
                    <td data-label="Speeltijd" className={`player-detail__column player-detail__column--number`}>
322
                      {game.minutesPlayed}'
323
                    </td>
324
                  </tr>
325
                )
326
              })}
327
            </tbody>
328
          </table>
329
        </Card>
330
      )
331
    }
332
  }
333
334
  renderPlayerBirthdate = (player) => (
335
    <div className={`player-detail__data-item player-detail__data-item--birthdate`}>
336
      <span className={`player-detail__data-item__label`}>Geboortedatum</span>
337
      <span className={`player-detail__data-item__data`}>{player.field_birth_date || `Onbekend`}</span>
338
    </div>
339
  )
340
  renderPlayerPosition = (player) => (
341
    <div className={`player-detail__data-item player-detail__data-item--position`}>
342
      <span className={`player-detail__date-item__data`}>
343
        {player.field_position && mapPositionCode(player.field_position)}
344
      </span>
345
      <span className={`player-detail__data-item__label`}>
346
        {player.relationships.node__team && (
347
          <Link to={player.relationships.node__team[0].path.alias}>{player.relationships.node__team[0].title}</Link>
348
        )}
349
      </span>
350
    </div>
351
  )
352
  renderPlayerJoinDate = (player) => {
353
    const currentlyPlaying = !player.field_date_leave
354
    return (
355
      <div className={`player-detail__data-item player-detail__data-item--joindate`}>
356
        <span className={`player-detail__data-item__label`}>
357
          {currentlyPlaying && `Speler bij KCVV sinds`}
358
          {!currentlyPlaying && `Speler tussen`}
359
        </span>
360
        <span className={`player-detail__data-item__data`}>
361
          {player.field_join_date || `Onbekend`}
362
          {!currentlyPlaying && (
363
            <Fragment>
364
              <span className={`text--regular`}> en </span> {player.field_date_leave}
365
            </Fragment>
366
          )}
367
        </span>
368
      </div>
369
    )
370
  }
371
  renderPlayerData = (player) => (
372
    <section className={`player-detail__data`}>
373
      {this.renderPlayerBirthdate(player)}
374
      {this.renderPlayerPosition(player)}
375
      {this.renderPlayerJoinDate(player)}
376
    </section>
377
  )
378
  renderPlayerBody = (player) => {
379
    const cleanBody =
380
      (player.body &&
381
        player.body.processed.replaceAll(`/sites/default/`, `${process.env.GATSBY_API_DOMAIN}/sites/default/`)) ||
382
      ``
383
384
    return (
385
      <section className={`player-detail__body`}>
386
        <div dangerouslySetInnerHTML={{ __html: cleanBody }} />
387
      </section>
388
    )
389
  }
390
  render() {
391
    const { player } = this.props
392
393
    const team = player.relationships.node__team || []
394
    const articles = player.relationships.node__article || []
395
396
    return (
397
      <Fragment>
398
        <article className={`player-detail`}>
399
          {this.renderPlayerHeader(player)}
400
          {this.renderPlayerStats(player)}
401
          <div className={`player-break`}></div>
402
          {this.renderPlayerData(player)}
403
          {this.renderPlayerBody(player)}
404
          {this.renderPlayerStatsFull(player)}
405
          {this.renderPlayerGamesFull(player)}
406
        </article>
407
408
        {(team || articles) && <RelatedNews items={team.concat(articles)} limit={6} />}
409
      </Fragment>
410
    )
411
  }
412
}
413
414
// Retrieve endpoint of the logo's api from the site metadata (gatsby-config.js).
415
const query = graphql`
416
  query {
417
    site {
418
      siteMetadata {
419
        kcvvPsdApi
420
      }
421
    }
422
  }
423
`
424
425
export default ({ player }) => (
426
  <StaticQuery
427
    query={query}
428
    render={(data) => (
429
      <PlayerDetail
430
        // Data is the result of our query.
431
        config={data}
432
        player={player}
433
      />
434
    )}
435
  />
436
)
437